package cz.af.portletExams.backend;

import cz.af.portletExams.backend.rest.ExamsClientHttpRequestFactory;
import cz.af.portletExams.backend.rest.SimpleModelConverter;
import cz.af.portletExams.backend.rest.converter.ExamConverter;
import cz.af.portletExams.backend.rest.converter.ExamsForSubjectsConverter;
import cz.af.portletExams.backend.rest.converter.RegistredExamsConverter;
import cz.af.portletExams.backend.rest.dto.ExamsForSubject;
import cz.af.portletExams.backend.rest.dto.RegisteredExams;
import cz.af.portletExams.model.Exam;
import cz.af.portletExams.model.Subject;
import org.apache.log4j.Logger;
import org.springframework.http.HttpHeaders;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.support.RestGatewaySupport;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ExamsOverViewBackendRest extends RestGatewaySupport implements ExamsOverViewBackend {

    private static final Logger log = Logger.getLogger(ExamsOverViewBackendRest.class);

    public static final String KOSAPI_AP = "https://kosapi.fit.cvut.cz/api/3b/";

    public ExamsOverViewBackendRest(ExamsClientHttpRequestFactory clientHttpRequestFactory) {
        super(clientHttpRequestFactory);
    }

    public void init() {
        final List<HttpMessageConverter<?>> list = new LinkedList<HttpMessageConverter<?>>();
        list.add(new ExamsForSubjectsConverter());
        list.add(new ExamConverter());
        list.add(new RegistredExamsConverter());

        list.add(new AtomFeedHttpMessageConverter());
        list.add(new StringHttpMessageConverter());
        getRestTemplate().setMessageConverters(list);
    }


    @Override
    public List<Subject> findSubjectsForUsername(String userName) {
        String uri = KOSAPI_AP;
        uri += "students/";
        uri += userName;
        uri += "/enrolledCourses";

        final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(uri);
        addSemesterArgument(uriComponentsBuilder);

        final String url = uriComponentsBuilder.build().encode().toUriString();
        final String string = getRestTemplate().getForObject(url, String.class);

        List<Subject> subjects = SimpleModelConverter.convertToSubjects(string);
        log.info("findSubjectsForUsername " + userName + "  subCount= " + subjects.size());
        return subjects;
    }

    @Override
    public Exam findExam(String examId) {
        String uri = KOSAPI_AP;
        uri += "exams/";
        uri += examId;

        final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(uri);
        addSemesterArgument(uriComponentsBuilder);
        uriComponentsBuilder.queryParam("fields", "id,content(startDate,capacity,occupied,course)");

        final String url = uriComponentsBuilder.build().encode().toUriString();

        final Exam exam = getRestTemplate().getForObject(url, Exam.class);
        return exam;
    }

    @Override
    public List<Exam> findExamsForSubject(String subjectId) {
        String uri = KOSAPI_AP;
        uri += "courses/";
        uri += subjectId;
        uri += "/exams";

        final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(uri);
        addSemesterArgument(uriComponentsBuilder);
        uriComponentsBuilder.queryParam("fields", "entry(id,content(startDate,capacity,occupied,course))");

        final String url = uriComponentsBuilder.build().encode().toUriString();

        final ExamsForSubject examsForSubject = getRestTemplate().getForObject(url, ExamsForSubject.class);
        log.info("findExamsForSubject " + subjectId + "  subCount= " + examsForSubject.getExams().size());
        return examsForSubject.getExams();
    }

    @Override
    public boolean isUsernameValid(String username) {
        String uri = KOSAPI_AP;
        uri += "students/";
        uri += username;

        final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(uri);
        addSemesterArgument(uriComponentsBuilder);

        final String url = uriComponentsBuilder.build().encode().toUriString();

        try {
            final HttpHeaders httpHeaders = getRestTemplate().headForHeaders(url);
            return true;
        } catch (HttpClientErrorException e) {
            return false;
        }
    }

    @Override
    public List<String> findExamIdsForUser(String username) {
        String uri = KOSAPI_AP;
        uri += "students/";
        uri += username;
        uri += "/registeredExams";

        final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(uri);
        addSemesterArgument(uriComponentsBuilder);
        uriComponentsBuilder.queryParam("fields", "entry(content(exam))");

        final String url = uriComponentsBuilder.build().encode().toUriString();
        final RegisteredExams response = getRestTemplate().getForObject(url, RegisteredExams.class);
        final List<String> examsIds = response.getExamsIds();
        log.info("findExamIdsForUser " + username + "  examsCount= " + examsIds.size());
        return examsIds;
    }

    @Override
    public List<Exam> findExamsForUser(String username) {
        final List<String> examIdsForUser = findExamIdsForUser(username);
        final List<Exam> exams = new ArrayList<Exam>();
        for (String examId : examIdsForUser) {
            exams.add(findExam(examId));
        }
        return exams;
    }

    private void addSemesterArgument(UriComponentsBuilder uriComponentsBuilder) {
//        Kód semestru má tvar CYYS, kde C značí století (A = 20. století, B = 21. století),
//        YY dvojčíslí roku a S semestr (1 = zimní, 2 = letní). Například zimní semestr roku 2010 se označuje B101.
//        uriComponentsBuilder.queryParam("sem", "none");
        uriComponentsBuilder.queryParam("sem", "B121");
    }
}
